#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

//数组名是首元素的地址，数组中的元素是整型，所以这个地址是整型指针
//所以在传递数组名作为实参时，他的接收形参部分为整型指针，int*

//int* arr2[20] = {};//指针数组，数组中的每一个元素都是指针，
//指针类型为int*   这里arr2的类型为指针，形参部分既可以用数组
//接收，也可以用指针接收  可以观察到每一个元素的类型都为int*,int*的地址为 int** 
//是一个二级指针


//int arr[3][5]={0};
//二维数组传参，形参可以是数组，形参数组的行和列的数字不可以全部省略
//可以表示为int arr[3][5]或者int arr[][5],行可以省略，列一定不能省略
//像int arr[][]这种形参是错误的


//二维数组传参，形参部分可以是指针，二维数组的每一个元素都是
//一维数组，一维数组的指针是数组指针 

//二维数组的数组名，是第一行一维数组的地址


//一级指针传参
//void print(int* p,int sz)
//{
//	int i = 0;
//	for (i=0;i<10;i++)
//	{
//		//打印出每一个元素
//		printf("%d\n",*(p+i));
//	}
//}
//int main()
//{
//	int arr[10] = {0,1,2,3,4,5,6,7,8,9};
//	int* p = arr;
//	int sz = sizeof(arr) / sizeof(arr[10]);//求解出元素的个数
//	print(arr,sz);//传给形参的是首元素的地址，该元素是一个整型
//	              //它的地址为整型指针，形参接收应为int* 
//	return 0;
//}

//void test(int** p)
//{
//	printf("%d\n",**p);
//}
//int main()
//{
//	int n = 10;
//	int* p = &n;
//	int** pp = &p;
//	test(pp);
//	test(&p);
//	return 0;
//}

//当函数为二级指针的形参时，可以传递的参数有，二级指针，一级指针的地址
//以及指针数组（怎么理解? 比如说，int* arr[10],有十个元素，每一个元素都是
//整型指针，指针数组传递arr为首元素的地址，为指针的指针，二级指针）
//int Add(int x,int y)
//{
//	return x + y;
//}
//int main()
//{
//	//printf("%p\n",&Add);
//
//	return 0;
//}


//首先pf是一个指针，它指向一个函数，函数用小括号表示
//小括号内存放函数形参的类型，为了确保*和pf结合，需要对*和pf
//加上小括号  最前面放置函数的类型  int (*pf)(int,int)

//&函数名和函数名是同一个地址

//利用函数指针调用函数，对函数进行解引用，右边的小括号内的为实参


//int Add(int x,int y)
//{
//	return x + y;
//}
//int main()
//{
//	//printf("%p\n",&Add);
//	//int (*pf)(int, int) = &Add;
//	int (*pf)(int, int) = Add;
//	//int ret = Add(2,3);
//	//int ret=(*pf)(2, 3);
//	int ret = pf(2, 3);
//	printf("%d",ret);
//	return 0;
//}

//通过函数指针去调用函数，*可以省略，也可以不省；但是如果没有省略的话，
//一定要添加括号


int* arr[3][3] = {1};//指针数组，数组里面的每一个元素都是指针
int p = **arr;//*arr=*(arr+0)=arr[0]//第一行的数组
printf("%d",p);